package main

import (
	"context"
	"device-modbus/config"
	"device-modbus/internal/biz/dal"
	"device-modbus/internal/plugin_manager"
	"device-modbus/internal/socket"
	"device-modbus/internal/transpond"
	"net/http"
	_ "net/http/pprof"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/cloudwego/hertz/pkg/app/server"
	"github.com/cloudwego/hertz/pkg/common/hlog"
)

// 重试配置参数
const (
	initRetryInterval = 5 * time.Second // 初始化重试间隔
	callMaxRetries    = 3               // 插件调用最大重试次数
	callRetryInterval = 2 * time.Second // 插件调用重试间隔
	maxQueueRetries   = 5               // 队列最大重试次数
	recoveryDelay     = 5 * time.Second // 服务恢复延迟
	gracefulShutdown  = 2 * time.Second // 优雅关闭等待时间
)

func main() {
	// 初始化日志配置
	hlog.SetLevel(hlog.LevelDebug)
	hlog.Info("服务开始启动...")
	go func() {
		http.ListenAndServe("127.0.0.1:9999", nil)
	}()
	// 加载配置
	config.LoadConfig("config.yaml")

	hlog.Info("配置文件加载成功")

	// 创建全局上下文，用于控制所有组件的生命周期
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	// 初始化数据访问层（关键组件，失败则终止）
	initDAL()

	// 启动队列（带重试机制）
	queue, err := startQueueWithRetry(ctx)
	if err != nil {
		hlog.Fatalf("队列启动失败: %v", err)
	}
	defer func() {
		if err := queue.Close(); err != nil {
			hlog.Errorf("关闭队列错误: %v", err)
		} else {
			hlog.Info("队列已关闭")
		}
	}()

	// 创建设备处理器
	deviceHandler := transpond.NewDeviceHandler(queue, "")

	// 启动Hertz服务器（带错误监控和自动恢复）
	hzServer, err := startHertzServer(ctx)
	if err != nil {
		hlog.Fatalf("Hertz服务器启动失败: %v", err)
	}

	// 启动发送器（带错误恢复）
	startSenderWithRecovery(ctx, queue)

	// 启动socket服务（带错误恢复）
	startSocketWithRecovery(ctx, deviceHandler)

	// 初始化插件管理器
	if err := initPluginManager(ctx); err != nil {
		hlog.Fatalf("插件管理器初始化失败: %v", err)
	}

	// 等待退出信号并优雅关闭
	waitForShutdownSignal(ctx, cancel, hzServer)
}

// 初始化数据访问层
func initDAL() {
	hlog.Info("初始化数据访问层...")
	dal.Init()
}

// 带重试机制启动队列
func startQueueWithRetry(ctx context.Context) (*transpond.Queue, error) {
	var queue *transpond.Queue
	var err error

	// 使用通用重试函数
	err = retryWithBackoff(maxQueueRetries, func(attempt int) error {
		var innerErr error
		queue, innerErr = transpond.NewQueue("requests.db")
		return innerErr
	})

	if err != nil {
		return nil, err
	}

	hlog.Info("队列初始化成功")
	return queue, nil
}

// 启动Hertz服务器并监控
func startHertzServer(ctx context.Context) (*server.Hertz, error) {
	// 从配置文件中获取HTTP监听地址
	listenAddr := config.DeviceConfig.Http.ListenAddr
	if listenAddr == "" {
		listenAddr = "0.0.0.0:8080"
	}

	hlog.Infof("准备在 %s 启动Hertz服务器", listenAddr)

	h := server.New(
		server.WithHostPorts(listenAddr),
		server.WithNetwork("tcp4"),
	)
	register(h)

	// 启动服务器（在单独的goroutine中）
	go func() {
		hlog.Info("Hertz服务器启动中...")
		if err := h.Run(); err != nil {
			hlog.Errorf("Hertz服务器异常: %v，尝试重启...", err)
			// 等待一段时间后尝试重启
			select {
			case <-ctx.Done():
				return
			case <-time.After(recoveryDelay):
				// 重启服务器
				if _, err := startHertzServer(ctx); err != nil {
					hlog.Fatalf("Hertz服务器重启失败: %v", err)
				}
			}
		}
	}()

	return h, nil
}

// 带错误恢复机制启动发送器
func startSenderWithRecovery(ctx context.Context, queue *transpond.Queue) {
	go func() {
		sender := transpond.NewSender(queue)
		hlog.Info("启动发送器...")

		for {
			select {
			case <-ctx.Done():
				hlog.Info("发送器收到关闭信号，退出")
				return
			default:
				// 发送器主逻辑
				sender.Start(ctx)
				// 如果退出，记录错误并重启
				hlog.Warn("发送器意外退出，将在5秒后重启")
				time.Sleep(recoveryDelay)
			}
		}
	}()
}

// 带错误恢复机制启动Socket服务
func startSocketWithRecovery(ctx context.Context, handler *transpond.DeviceHandler) {
	go func() {
		cfg := socket.DefaultConfig()
		// 获取config.yml中的server.port
		cfg.ListenAddr = config.DeviceConfig.Server.ListenAddr
		if cfg.ListenAddr == "" {
			cfg.ListenAddr = "tcp://0.0.0.0:9000"
		}
		hlog.Infof("准备在 %s 启动Socket服务", cfg.ListenAddr)

		for {
			select {
			case <-ctx.Done():
				hlog.Info("Socket服务收到关闭信号，退出")
				return
			default:
				// Socket服务主逻辑
				if err := socket.Start(ctx, handler, cfg); err != nil {
					hlog.Errorf("Socket服务异常退出: %v，将在5秒后重启", err)
				} else {
					hlog.Warn("Socket服务正常退出，将在5秒后重启")
				}
				time.Sleep(recoveryDelay)
			}
		}
	}()
}

// 初始化插件管理器
func initPluginManager(ctx context.Context) error {
	// 配置插件管理器
	opts := plugin_manager.Options{
		CheckInterval:   30 * time.Second, // 连接检查间隔
		HeartbeatFreq:   10 * time.Second, // 心跳频率
		MaxConnWorkers:  5,                // 最大连接并发数
		MaxHeartWorkers: 10,               // 最大心跳并发数
		EnableMetrics:   true,             // 启用指标收集
	}

	hlog.Info("初始化插件管理器...")
	// 初始化全局管理器
	if err := plugin_manager.InitGlobalManager(opts); err != nil {
		return err
	}

	// 启动插件管理器监控goroutine
	go func() {
		defer func() {
			if manager, err := plugin_manager.GetGlobalManager(); err == nil {
				manager.Stop()
				hlog.Info("插件管理器已停止")
			}
		}()

		hlog.Info("插件管理器启动成功")
		// 等待上下文结束信号
		<-ctx.Done()
		hlog.Info("插件管理器收到关闭信号，开始停止")
	}()

	return nil
}

// 等待并处理关闭信号
func waitForShutdownSignal(ctx context.Context, cancel context.CancelFunc, hzServer *server.Hertz) {
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, os.Interrupt)

	// 等待退出信号
	sig := <-sigChan
	hlog.Infof("收到退出信号: %v，开始优雅关闭", sig)

	// 触发全局关闭
	cancel()

	// 给组件时间处理剩余任务
	hlog.Info("等待组件完成剩余任务...")
	time.Sleep(gracefulShutdown)

	// 关闭Hertz服务器
	if hzServer != nil {
		if err := hzServer.Close(); err != nil {
			hlog.Errorf("关闭Hertz服务器错误: %v", err)
		} else {
			hlog.Info("Hertz服务器已关闭")
		}
	}

	hlog.Info("所有组件已关闭，服务退出")
}

// 通用重试函数 - 带指数退避
func retryWithBackoff(maxRetries int, fn func(attempt int) error) error {
	var err error
	for attempt := 0; attempt < maxRetries; attempt++ {
		if err = fn(attempt); err == nil {
			return nil
		}

		hlog.Errorf("操作失败 (第%d次重试): %v", attempt+1, err)

		// 最后一次尝试失败则直接返回
		if attempt == maxRetries-1 {
			break
		}

		// 指数退避：1s, 2s, 4s... 最多10秒
		sleepDuration := time.Duration(1<<attempt) * time.Second
		if sleepDuration > 10*time.Second {
			sleepDuration = 10 * time.Second
		}
		time.Sleep(sleepDuration)
	}
	return err
}
